home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Graphics / Ghostscript / source / iscanbin.c < prev    next >
C/C++ Source or Header  |  1996-01-23  |  18KB  |  577 lines

  1. /* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* iscanbin.c */
  20. /* Ghostscript binary token scanner */
  21. #include "math_.h"
  22. #include "memory_.h"
  23. #include "ghost.h"
  24. #include "gsutil.h"
  25. #include "stream.h"
  26. #include "strimpl.h"        /* for sfilter.h */
  27. #include "sfilter.h"        /* for iscan.h */
  28. #include "errors.h"
  29. #include "ialloc.h"
  30. #include "idict.h"
  31. #include "dstack.h"            /* for immediately evaluated names */
  32. #include "ostack.h"        /* must precede iscan.h */
  33. #include "iname.h"
  34. #include "iscan.h"            /* for scan_Refill */
  35. #include "iutil.h"
  36. #include "ivmspace.h"
  37. #include "store.h"
  38. #include "bseq.h"
  39. #include "btoken.h"
  40. #include "ibnum.h"
  41.  
  42. /* Define the number of required initial bytes for binary tokens. */
  43. const byte bin_token_bytes[] = { bin_token_bytes_values };
  44.  
  45. /* Import the system and user name tables */
  46. extern ref system_names, user_names;
  47.  
  48. /* Forward references */
  49. private int scan_bin_num_array_continue(P3(stream *, ref *, scanner_state *));
  50. private int scan_bin_string_continue(P3(stream *, ref *, scanner_state *));
  51. private int scan_bos_continue(P3(stream *, ref *, scanner_state *));
  52. private byte *scan_bos_resize(P3(scanner_state *, uint, uint));
  53. private int scan_bos_string_continue(P3(stream *, ref *, scanner_state *));
  54.  
  55. /* Scan a binary token.  Called from the main scanner */
  56. /* when it encounters an ASCII code 128-159, */
  57. /* if binary tokens are being recognized (object format != 0). */
  58. #define pbs (&pstate->s_ss.binary)
  59. int
  60. scan_binary_token(stream *s, ref *pref, scanner_state *pstate)
  61. {    s_declare_inline(s, p, rlimit);
  62. #define return_skip(n) { p += n; s_end_inline(s, p, rlimit); return 0; }
  63.     int num_format, code;
  64.     uint arg;
  65.     uint wanted;
  66.     uint rcnt;
  67.     s_begin_inline(s, p, rlimit);
  68.     wanted = binary_token_bytes(*p) - 1;
  69.     rcnt = rlimit - p;
  70. #define return_refill()\
  71.   { sputback_inline(s, p, rlimit); s_end_inline(s, p, rlimit);\
  72.     pstate->s_scan_type = scanning_none; return scan_Refill;\
  73.   }
  74.     if ( rcnt < wanted )
  75.         return_refill();
  76.     switch ( *p )
  77.        {
  78.     case bt_seq_IEEE_msb:
  79.         num_format = num_msb + num_float_IEEE; goto bseq;
  80.     case bt_seq_IEEE_lsb:
  81.         num_format = num_lsb + num_float_IEEE; goto bseq;
  82.     case bt_seq_native_msb:
  83.         num_format = num_msb + num_float_native; goto bseq;
  84.     case bt_seq_native_lsb:
  85.         num_format = num_lsb + num_float_native;
  86. bseq:        pbs->num_format = num_format;
  87.       {    uint top_size = p[1];
  88.         uint hsize, size;
  89.         if ( top_size == 0 )
  90.           {    /* Extended header (2-byte array size, */
  91.             /* 4-byte length) */
  92.             ulong lsize;
  93.             if ( rcnt < 7 )
  94.                 return_refill();
  95.             top_size = sdecodeshort(p + 2, num_format);
  96.             lsize = sdecodelong(p + 4, num_format);
  97.             if ( (size = lsize) != lsize )
  98.                 return_error(e_limitcheck);
  99.             hsize = 8;
  100.           }
  101.         else
  102.           {    /* Normal header (1-byte array size, 2-byte length). */
  103.             /* We already checked rcnt >= 3. */
  104.             size = sdecodeshort(p + 2, num_format);
  105.             hsize = 4;
  106.           }
  107.         if ( size < hsize )
  108.             return_error(e_syntaxerror);
  109.         /* Preallocate an array large enough for the worst case, */
  110.         /* namely, all objects and no strings. */
  111.         code = ialloc_ref_array(&pbs->bin_array,
  112.                     a_all + a_executable,
  113.                     size / sizeof(ref),
  114.                     "binary object sequence(objects)");
  115.         if ( code < 0 )
  116.             return code;
  117.         p += hsize - 1;
  118.         size -= hsize;
  119.         s_end_inline(s, p, rlimit);
  120.         pbs->max_array_index = pbs->top_size = top_size;
  121.         pbs->min_string_index = pbs->size = size;
  122.         pbs->index = 0;
  123.       }
  124.         pstate->s_da.is_dynamic = false;
  125.         pstate->s_da.base = pstate->s_da.next =
  126.           pstate->s_da.limit = pstate->s_da.buf;
  127.         code = scan_bos_continue(s, pref, pstate);
  128.         if ( code == scan_Refill || code < 0 )
  129.           {    /* Clean up array for GC. */
  130.             uint index = pbs->index;
  131.             refset_null(pbs->bin_array.value.refs + index,
  132.                     r_size(&pbs->bin_array) - index);
  133.             pbs->cont = scan_bos_continue;
  134.           }
  135.         return code;
  136.     case bt_int32_msb:
  137.         num_format = num_msb + num_int32; goto num;
  138.     case bt_int32_lsb:
  139.         num_format = num_lsb + num_int32; goto num;
  140.     case bt_int16_msb:
  141.         num_format = num_msb + num_int16; goto num;
  142.     case bt_int16_lsb:
  143.         num_format = num_lsb + num_int16; goto num;
  144.     case bt_int8:
  145.         make_int(pref, (p[1] ^ 128) - 128);
  146.         return_skip(1);
  147.     case bt_fixed:
  148.         num_format = p[1];
  149.         if ( !num_is_valid(num_format) )
  150.             return_error(e_syntaxerror);
  151.         wanted = 1 + encoded_number_bytes(num_format);
  152.         if ( rcnt < wanted )
  153.             return_refill();
  154.         code = sdecode_number(p + 2, num_format, pref);
  155.         goto rnum;
  156.     case bt_float_IEEE_msb:
  157.         num_format = num_msb + num_float_IEEE; goto num;
  158.     case bt_float_IEEE_lsb:
  159.         num_format = num_lsb + num_float_IEEE; goto num;
  160.     case bt_float_native:
  161.         num_format = num_float_native;
  162. num:        code = sdecode_number(p + 1, num_format, pref);
  163. rnum:        switch ( code )
  164.            {
  165.         case t_integer: case t_real:
  166.             r_set_type(pref, code);
  167.             break;
  168.         case t_null:
  169.             return_error(e_syntaxerror);
  170.         default:
  171.             return code;
  172.            }
  173.         return_skip(wanted);
  174.     case bt_boolean:
  175.         arg = p[1];
  176.         if ( arg & ~1 )
  177.             return_error(e_syntaxerror);
  178.         make_bool(pref, arg);
  179.         return_skip(1);
  180.     case bt_string_256:
  181.         arg = p[1]; p++; goto str;
  182.     case bt_string_64k_msb:
  183.         arg = (p[1] << 8) + p[2]; p += 2; goto str;
  184.     case bt_string_64k_lsb:
  185.         arg = p[1] + (p[2] << 8); p += 2; goto str;
  186. str:       {    byte *str = ialloc_string(arg, "string token");
  187.         if ( str == 0 )
  188.             return_error(e_VMerror);
  189.         s_end_inline(s, p, rlimit);
  190.         pstate->s_da.base = pstate->s_da.next = str;
  191.         pstate->s_da.limit = str + arg;
  192.         code = scan_bin_string_continue(s, pref, pstate);
  193.         if ( code == scan_Refill || code < 0 )
  194.           {    pstate->s_da.is_dynamic = true;
  195.             make_null(&pbs->bin_array);    /* clean up for GC */
  196.             pbs->cont = scan_bin_string_continue;
  197.           }
  198.         return code;
  199.        }
  200.     case bt_litname_system:
  201.         code = array_get(&system_names, p[1], pref);
  202.         goto lname;
  203.     case bt_execname_system:
  204.         code = array_get(&system_names, p[1], pref);
  205.         goto xname;
  206.     case bt_litname_user:
  207.         code = array_get(&user_names, p[1], pref);
  208. lname:        if ( code < 0 ) return code;
  209.         if ( !r_has_type(pref, t_name) )
  210.             return_error(e_undefined);
  211.         return_skip(1);
  212.     case bt_execname_user:
  213.         code = array_get(&user_names, p[1], pref);
  214. xname:        if ( code < 0 ) return code;
  215.         if ( !r_has_type(pref, t_name) )
  216.             return_error(e_undefined);
  217.         r_set_attrs(pref, a_executable);
  218.         return_skip(1);
  219.     case bt_num_array:
  220.         num_format = p[1];
  221.         if ( !num_is_valid(num_format) )
  222.             return_error(e_syntaxerror);
  223.         arg = sdecodeshort(p + 2, num_format);
  224.         code = ialloc_ref_array(&pbs->bin_array, a_all, arg,
  225.                     "number array token");
  226.         if ( code < 0 )
  227.             return code;
  228.         pbs->num_format = num_format;
  229.         pbs->index = 0;
  230.         p += 3;
  231.         s_end_inline(s, p, rlimit);
  232.         code = scan_bin_num_array_continue(s, pref, pstate);
  233.         if ( code == scan_Refill || code < 0 )
  234.           {    /* Make sure the array is clean for the GC. */
  235.             refset_null(pbs->bin_array.value.refs + pbs->index,
  236.                     arg - pbs->index);
  237.             pbs->cont = scan_bin_num_array_continue;
  238.           }
  239.         return code;
  240.        }
  241.     return_error(e_syntaxerror);
  242. }
  243.  
  244. /* Continue collecting a binary string. */
  245. private int
  246. scan_bin_string_continue(stream *s, ref *pref, scanner_state *pstate)
  247. {    byte *q = pstate->s_da.next;
  248.     uint wanted = pstate->s_da.limit - q;
  249.     uint rcnt;
  250.     sgets(s, q, wanted, &rcnt);
  251.     if ( rcnt == wanted )
  252.       {    /* Finished collecting the string. */
  253.         make_string(pref, a_all | icurrent_space,
  254.                 pstate->s_da.limit - pstate->s_da.base,
  255.                 pstate->s_da.base);
  256.         return 0;
  257.       }
  258.     pstate->s_da.next = q + rcnt;
  259.     pstate->s_scan_type = scanning_binary;
  260.     return scan_Refill;
  261. }
  262.  
  263. /* Continue scanning a binary number array. */
  264. private int
  265. scan_bin_num_array_continue(stream *s, ref *pref, scanner_state *pstate)
  266. {    uint index = pbs->index;
  267.     ref *np = pbs->bin_array.value.refs + index;
  268.     uint wanted = encoded_number_bytes(pbs->num_format);
  269.     for ( ; index < r_size(&pbs->bin_array); index++, np++ )
  270.       {    int code;
  271.         if ( sbufavailable(s) < wanted )
  272.           {    pbs->index = index;
  273.             pstate->s_scan_type = scanning_binary;
  274.             return scan_Refill;
  275.           }
  276.         code = sdecode_number(sbufptr(s), pbs->num_format, np);
  277.         switch ( code )
  278.           {
  279.         case t_integer: case t_real:
  280.             r_set_type(np, code);
  281.             sbufskip(s, wanted);
  282.             break;
  283.         case t_null:
  284.             return_error(e_syntaxerror);
  285.         default:
  286.             return code;
  287.           }
  288.       }
  289.     *pref = pbs->bin_array;
  290.     return 0;
  291. }
  292.  
  293. /*
  294.  * Continue scanning a binary object sequence.  We preallocated space for
  295.  * the largest possible number of objects, but not for strings, since
  296.  * the latter would probably be a gross over-estimate.  Instead,
  297.  * we wait until we see the first string or name, and allocate string space
  298.  * based on the hope that its string index is the smallest one we will see.
  299.  * If this turns out to be wrong, we may have to reallocate, and adjust
  300.  * all the pointers.
  301.  */
  302. #define sizeof_bin_seq_obj ((uint)sizeof(bin_seq_obj))
  303. private int
  304. scan_bos_continue(register stream *s, ref *pref, scanner_state *pstate)
  305. {    s_declare_inline(s, p, rlimit);
  306.     uint max_array_index = pbs->max_array_index;
  307.     uint min_string_index = pbs->min_string_index;
  308.     int format = pbs->num_format;
  309. #if arch_is_big_endian
  310. #  define must_swap_bytes num_is_lsb(format)
  311. #else
  312. #  define must_swap_bytes !num_is_lsb(format)
  313. #endif
  314.     uint index = pbs->index;
  315.     uint size = pbs->size;
  316.     ref *abase = pbs->bin_array.value.refs;
  317.     int code;
  318.     s_begin_inline(s, p, rlimit);
  319.     for ( ; index < max_array_index; index++ )
  320.        {    bin_seq_obj ob;
  321.         byte bt;
  322.         ref *op = abase + index;
  323.         uint atype, sattrs;
  324.         s_end_inline(s, p, rlimit);    /* in case of error */
  325.         if ( rlimit - p < sizeof_bin_seq_obj )
  326.           {    pbs->index = index;
  327.             pbs->max_array_index = max_array_index;
  328.             pbs->min_string_index = min_string_index;
  329.             pstate->s_scan_type = scanning_binary;
  330.             return scan_Refill;
  331.           }
  332.         memcpy(&ob, p + 1, sizeof_bin_seq_obj);
  333.         p += sizeof_bin_seq_obj;
  334. #define do_swap_size()\
  335.   bt = ob.size.b[0], ob.size.b[0] = ob.size.b[1], ob.size.b[1] = bt
  336. #define swap_size()\
  337.   if ( must_swap_bytes ) do_swap_size()
  338. #define do_swap_value()\
  339.   bt = ob.value.b[0], ob.value.b[0] = ob.value.b[3], ob.value.b[3] = bt,\
  340.   bt = ob.value.b[1], ob.value.b[1] = ob.value.b[2], ob.value.b[2] = bt
  341. #define swap_value()\
  342.   if ( must_swap_bytes ) do_swap_value()
  343. #define swap_size_also_value()\
  344.   if ( must_swap_bytes ) do_swap_size(), do_swap_value()
  345.         switch ( ob.tx & 0x7f )
  346.           {
  347.         case bs_null:
  348.             make_null(op); break;
  349.         case bs_integer:
  350.             swap_value();
  351.             make_int(op, ob.value.w);
  352.             break;
  353.         case bs_real:
  354.             if ( ob.size.w != 0 )    /* fixed-point number */
  355.                {    swap_size_also_value();
  356.                 ob.value.f = (float)ldexp((float)ob.value.w,
  357.                               -ob.size.w);
  358.                }
  359.             else if ( (format & ~(num_lsb | num_msb)) !=
  360.                   num_float_native
  361.                 )
  362.                {    ob.value.f = sdecodefloat(ob.value.b, format);
  363.                }
  364.             make_real(op, ob.value.f);
  365.             break;
  366.         case bs_boolean:
  367.             swap_value();
  368.             make_bool(op, (ob.value.w == 0 ? 0 : 1));
  369.             break;
  370.         case bs_string:
  371.             swap_size_also_value();
  372.             sattrs = (ob.tx < 128 ? a_all : a_all + a_executable);
  373. str:            if ( ob.size.w == 0 )
  374.               {    /* For zero-length strings, the offset */
  375.                 /* doesn't matter, and may be zero. */
  376.                 make_empty_string(op, sattrs);
  377.                 break;
  378.               }
  379.             if ( ob.value.w < max_array_index * sizeof_bin_seq_obj ||
  380.                 ob.value.w + ob.size.w > size
  381.                )
  382.               return_error(e_syntaxerror);
  383.             if ( ob.value.w < min_string_index )
  384.               {    /* We have to (re)allocate the strings. */
  385.                 uint str_size = size - ob.value.w;
  386.                 byte *sbase;
  387.                 if ( pstate->s_da.is_dynamic )
  388.                   sbase = scan_bos_resize(pstate, str_size,
  389.                               index);
  390.                 else
  391.                   sbase = ialloc_string(str_size,
  392.                             "bos strings");
  393.                 if ( sbase == 0 )
  394.                   return_error(e_VMerror);
  395.                 pstate->s_da.is_dynamic = true;
  396.                 pstate->s_da.base = pstate->s_da.next = sbase;
  397.                 pstate->s_da.limit = sbase + str_size;
  398.                 min_string_index = ob.value.w;
  399.               }
  400.             make_string(op, sattrs | icurrent_space, ob.size.w,
  401.                     pstate->s_da.base +
  402.                       (ob.value.w - min_string_index));
  403.             break;
  404.         case bs_name:
  405.             sattrs = (ob.tx < 128 ? 0 : a_executable);
  406.             goto nam;
  407.         case bs_eval_name:
  408.             sattrs = a_readonly;
  409. nam:            swap_size_also_value();
  410.             switch ( ob.size.w )
  411.                {
  412.             case 0:
  413.                 code = array_get(&user_names, ob.value.w, op);
  414.                 goto usn;
  415.             case 0xffff:
  416.                 code = array_get(&system_names, ob.value.w, op);
  417. usn:                if ( code < 0 )
  418.                     return code;
  419.                 if ( !r_has_type(op, t_name) )
  420.                     return_error(e_undefined);
  421.                 r_set_attrs(op, sattrs);
  422.                 break;
  423.             default:
  424.                 goto str;
  425.               }
  426.             break;
  427.         case bs_array:
  428.             swap_size_also_value();
  429.             atype = t_array;
  430. arr:            if ( ob.value.w + ob.size.w > min_string_index ||
  431.                 ob.value.w & (sizeof_bin_seq_obj - 1)
  432.                )
  433.               return_error(e_syntaxerror);
  434.           {    uint aindex = ob.value.w / sizeof_bin_seq_obj;
  435.             max_array_index =
  436.               max(max_array_index, aindex + ob.size.w);
  437.             make_tasv_new(op, atype,
  438.                       (ob.tx < 128 ? a_all :
  439.                        a_all + a_executable) | icurrent_space,
  440.                       ob.size.w, refs, abase + aindex);
  441.           }
  442.             break;
  443.         case bs_dictionary:        /* EXTENSION */
  444.             swap_size_also_value();
  445.             if ( (ob.size.w & 1) != 0 && ob.size.w != 1 )
  446.               return_error(e_syntaxerror);
  447.             atype = t_mixedarray;    /* mark as dictionary */
  448.             goto arr;
  449.         case bs_mark:
  450.             make_mark(op); break;
  451.         default:
  452.             return_error(e_syntaxerror);
  453.           }
  454.        }
  455.     s_end_inline(s, p, rlimit);
  456.     /* Shorten the objects to remove the space that turned out */
  457.     /* to be used for strings. */
  458.     iresize_ref_array(&pbs->bin_array, max_array_index,
  459.               "binary object sequence(objects)");
  460.     code = scan_bos_string_continue(s, pref, pstate);
  461.     if ( code == scan_Refill )
  462.       {    pbs->cont = scan_bos_string_continue;
  463.       }
  464.     return code;
  465. }
  466.  
  467. /* Reallocate the strings for a binary object sequence, */
  468. /* adjusting all the pointers to them from objects. */
  469. private byte *
  470. scan_bos_resize(scanner_state *pstate, uint new_size, uint index)
  471. {    uint old_size = da_size(&pstate->s_da);
  472.     byte *old_base = pstate->s_da.base;
  473.     byte *new_base = iresize_string(old_base, old_size, new_size,
  474.                     "scan_bos_resize");
  475.     byte *relocated_base = new_base + (new_size - old_size);
  476.     uint i;
  477.     ref *aptr = pbs->bin_array.value.refs;
  478.     if ( new_base == 0 )
  479.       return 0;
  480.     /* Since the allocator normally extends strings downward, */
  481.     /* it's quite possible that new and old addresses are the same. */
  482.     if ( relocated_base != old_base )
  483.       for ( i = index; i != 0; i--, aptr++ )
  484.         if ( r_has_type(aptr, t_string) && r_size(aptr) != 0 )
  485.           aptr->value.bytes =
  486.         aptr->value.bytes - old_base + relocated_base;
  487.     return new_base;
  488. }
  489.  
  490. /* Continue reading the strings for a binary object sequence. */
  491. private int
  492. scan_bos_string_continue(register stream *s, ref *pref, scanner_state *pstate)
  493. {    ref rstr;
  494.     ref *op = pbs->bin_array.value.refs;
  495.     int code = scan_bin_string_continue(s, &rstr, pstate);
  496.     uint space = ialloc_space(idmemory);
  497.     bool rescan = false;
  498.     uint i;
  499.  
  500.     if ( code != 0 )
  501.         return code;
  502.     /* Finally, fix up names and dictionaries. */
  503.     for ( i = r_size(&pbs->bin_array); i != 0; i--, op++ )
  504.       switch ( r_type(op) )
  505.        {
  506.     case t_string:
  507.         if ( r_has_attr(op, a_write) )    /* a real string */
  508.           break;
  509.         /* This is actually a name; look it up now. */
  510.       {    uint sattrs =
  511.           (r_has_attr(op, a_executable) ? a_executable : 0);
  512.         code = name_ref(op->value.bytes, r_size(op), op, 1);
  513.         if ( code < 0 )
  514.           return code;
  515.         r_set_attrs(op, sattrs);
  516.       }
  517.         /* falls through */
  518.     case t_name:
  519.         if ( r_has_attr(op, a_read) )    /* bs_eval_name */
  520.            {    ref *defp = dict_find_name(op);
  521.             if ( defp == 0 )
  522.                 return_error(e_undefined);
  523.             store_check_space(space, defp);
  524.             ref_assign(op, defp);
  525.            }
  526.         break;
  527.     case t_mixedarray:        /* actually a dictionary */
  528.         {    uint count = r_size(op);
  529.             ref rdict;
  530.             if ( count == 1 )
  531.               {    /* Indirect reference. */
  532.                 if ( op->value.refs < op )
  533.                   ref_assign(&rdict, op->value.refs);
  534.                 else
  535.                   {    rescan = true;
  536.                     continue;
  537.                   }
  538.               }
  539.             else
  540.               {    code = dict_create(count >> 1, &rdict);
  541.                 if ( code < 0 )
  542.                   return code;
  543.                 while ( count )
  544.                   {    count -= 2;
  545.                     code = dict_put(&rdict,
  546.                             &op->value.refs[count],
  547.                             &op->value.refs[count + 1]);
  548.                     if ( code < 0 )
  549.                       return code;
  550.                   }
  551.               }
  552.             r_set_attrs(&rdict, a_all);
  553.             r_copy_attrs(&rdict, a_executable, op);
  554.             ref_assign(op, &rdict);
  555.         }
  556.         break;
  557.        }
  558.     /* If there were any forward indirect references, */
  559.     /* fix them up now. */
  560.     if ( rescan )
  561.       for ( op = pbs->bin_array.value.refs, i = r_size(&pbs->bin_array);
  562.             i != 0; i--, op++
  563.           )
  564.         if ( r_has_type(op, t_mixedarray) )
  565.           {    const ref *piref = op->value.const_refs;
  566.         ref rdict;
  567.         if ( r_has_type(piref, t_mixedarray) )    /* ref to indirect */
  568.           return_error(e_syntaxerror);
  569.         ref_assign(&rdict, piref);
  570.         r_copy_attrs(&rdict, a_executable, op);
  571.         ref_assign(op, &rdict);
  572.           }
  573.     ref_assign(pref, &pbs->bin_array);
  574.     r_set_size(pref, pbs->top_size);
  575.     return scan_BOS;
  576. }
  577.